package com.bestv.search.engine.analyzer;

import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.Tokenizer;

import java.io.Reader;

/**
 * @author Michael Wang
 */
public class SuggestionTokenizer extends Tokenizer {

    private final static int MAX_WORD_LEN = 255;
    private final char[] buffer = new char[MAX_WORD_LEN];
    private final static int IO_BUFFER_SIZE = 1024;
    private final char[] ioBuffer = new char[IO_BUFFER_SIZE];
    private int suggestionCharType = Character.OTHER_LETTER;
    private int offset = 0, bufferIndex = 0, dataLen = 0;
    private int length;
    private int start;
    public SuggestionTokenizer(Reader in) {
        input = in;
    }

    private final void push(char c) {
        if (length == 0)
            start = offset - 1; // start of token
        buffer[length++] = Character.toLowerCase(c); // buffer it
    }

    private final Token flush(final Token token) {
        if (length > 0) {
            return token.reinit(buffer, 0, length, start, start + length);
        } else
            return null;
    }

    @Override
    public final Token next(final Token reusableToken)
            throws java.io.IOException {
        assert reusableToken != null;
        length = 0;
        start = offset;

        while (true) {
            final char c;
            offset++;

            if (bufferIndex >= dataLen) {
                dataLen = input.read(ioBuffer);
                bufferIndex = 0;
                suggestionCharType = Character.getType(ioBuffer[0]);
            }

            if (dataLen == -1)
                return flush(reusableToken);
            else
                c = ioBuffer[bufferIndex++];

            if (Character.getType(c) == suggestionCharType) {
                if (length > 0) {
                    bufferIndex--;
                    offset--;
                    return flush(reusableToken);
                }
                push(c);
                return flush(reusableToken);
            }

            /*
             * switch (Character.getType(c)) { case
             * Character.DECIMAL_DIGIT_NUMBER: case Character.LOWERCASE_LETTER:
             * case Character.UPPERCASE_LETTER: push(c); if (length ==
             * MAX_WORD_LEN) return flush(reusableToken); break; case
             * Character.OTHER_LETTER: if (length > 0) { bufferIndex--;
             * offset--; return flush(reusableToken); } push(c); return
             * flush(reusableToken); default: if (length > 0) return
             * flush(reusableToken); break; }
             */
        }
    }
}
